package com.unc.allergyex.objects.tasks;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

import com.unc.allergyex.AllergyEX;
import com.unc.allergyex.helpers.ObjManager;
import com.unc.allergyex.helpers.Updater;
import com.unc.allergyex.objects.VersionResult;

/**This is an implementation of the android AsyncTask class.  It exists to 
 * spawn a separate thread to execute server queries.  This task is performed
 * in the doInBackground method.  The onPreExecute and onPostExecute methods 
 * are executed in the gui (main) thread of the given context; this is 
 * necessary because the gui library is not thread-safe.
 * @author Stephanie
 *
 */
public class UpdateTask extends AsyncTask<Context, Void, VersionResult> {
	Context context; //the context in which to execute gui commands
	private ProgressDialog dialog;
	private boolean cancelled;
	final String RESTAURANTS_CHANGED_MESSAGE = "AllergyEX now has updated restaurant information!";
	public final static String ALLERGENS_CHANGED_MESSAGE = "AllergyEX has updated allergen support!  Please edit your allergies accordingly.";
	final String INITIAL_BLOCKING_MESSAGE = "Pre-loading data from server...";
	final String INITIAL_LOAD_GREETING = "AllergyEX has successfully pre-loaded data!  Notifications of updated support will appear here!";

	public void onCancelled(){
		Log.e("STEPH", "okay, i been cancelled");
		this.cancelled = true;
		if (dialog != null){
			dialog.dismiss();
		}
	}
	
	/**This is a method to be called after creating the task to set the context.
	 * It is needed because the context must already be set before execute is called, 
	 * so that the preexecute method will have access to the context.
	 * @param context the context in which to draw notifications
	 */
	public void setContext(Context context){
		this.context = context;
		this.cancelled = false;
	}
	
	/**This is executed before doInBackground when execute is called.  
	 * The goal is to detect whether this is a first install and, if it
	 * is, to keep the user from interacting with the screen until the 
	 * first update from the server succeeds.  We accomplish this by 
	 * setting an indeterminate ProgressDialog.
	 * @see android.os.AsyncTask#onPreExecute()
	 */
	protected void onPreExecute(){
		if (ObjManager.isFreshInstall(context)){
			dialog = new ProgressDialog(context);
	        dialog.setMessage(INITIAL_BLOCKING_MESSAGE);
	        dialog.setIndeterminate(true);
	        dialog.setCancelable(false);
	        dialog.show();
		}
	}

	/**This is where the actual update is performed, through the use
	 * of Updater.  The parameter is the context into which response notifications
	 * should be created.
	 * The return value is a VersionResult object, which is returned from the
	 * Updater.checkForUpdates method and is used to encapsulate what
	 * needs to be updated.  
	 * @see android.os.AsyncTask#doInBackground(Params[])
	 */
	protected VersionResult doInBackground(Context... c) {
		context = c[0];
		Updater updater = new Updater(context);
		VersionResult result = updater.checkForUpdates();
		if (cancelled){
			result = new VersionResult(false, false, false, "hi");
		}
		return result;
	}	

	/**Executed after doInBackground.
	 * Dismiss the dialog, then based on the result of the query, 
	 * toast some information to the user and re-populate
	 * the gui and ObjManager.
	 * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
	 */
	protected void onPostExecute(VersionResult result){
		if (cancelled == false){
			if (dialog != null){ //dismiss the dialog if it was a fresh install and we drew one
				dialog.dismiss();
				if (!result.isError()){
					toast(INITIAL_LOAD_GREETING);
				}
			}
			if (result.isError()){ //if updater gave us an error, toast that error to the user
				toast(result.getMessage());
				return;
			}
			if (result.isRestaurantsChanged() && dialog == null){ //if the restaurants version was changed and this is not the first install, toast
				toast(RESTAURANTS_CHANGED_MESSAGE);
			}
			if (result.isAllergensChanged() || result.isRestaurantsChanged()){ //if either was changed, reload data and re-do autocomplete
				AllergyEX c = (AllergyEX) context;
				c.loadDataFromLocalStorage();
				c.setUpAutoComplete();
				c.checkForUnacknowledgedAllergenUpdate();
			}
		}
	}
	
	/**this is a helper method for making toasts
	 * @param message a string to toast to the user
	 */
	protected void toast(String message){
		Toast.makeText(context, message, Toast.LENGTH_LONG).show();
	}
}